/* Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
/*
 * @description: http请求封装
 * @fileName: request.ts
 * @author: zoujunjie
 * @date: 2022-07-05
 */
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { ElMessage as Message } from "element-plus";
// import store from '@/store'
import localTokenStrategy from "./util/auth.js";

interface ResponseData {
  isOK: boolean;
  data: any;
  code: number;
}
class HeaderBuilder {
  headers: any;
  constructor(headers: any) {
    this.headers = headers;
  }

  add(key: string, val: any) {
    this.headers[key] = val;
    return this;
  }

  build() {
    return this.headers;
  }
}

// const refreshToken = (refreshToken: string) => {
//   const isAdmin = localTokenStrategy.getUserInfo().isAdmin;
//   axios({
//     method: "POST",
//     url: isAdmin ? "/api/manager/refresh" : "/api/user/refresh",
//     data: {
//       refreshToken,
//     },
//   }).then((res) => {
//     const result = res.data;
//     localTokenStrategy.setToken(result.data.token);
//     result.data.user.isChief = result.data.chief;
//     result.data.user.isAdmin = isAdmin;
//     localTokenStrategy.setUserInfo(result.data.user);
//   });
// };

//const localTokenStrategy = new LocalTokenStrategy()

// create an axios instance
const service: AxiosInstance = axios.create({
  //baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  withCredentials: true, // send cookies when cross-domain requests
  timeout: 15000, // request timeout
});

let refreshSubscribers: any[] = [];

function subscribeTokenRefresh(cb: any) {
  refreshSubscribers.push(cb);
}

let isRefreshing = false;

function onRefreshed(token: string) {
  refreshSubscribers.map((x) => x(token));
}

const refreshToken = async (): Promise<string> => {
  let access = localTokenStrategy.__getTokenObj();
  let refreshToken = access.accessRefresh;
  let isAdmin = localTokenStrategy.getUserInfo().isAdmin;
  return axios
    .post(isAdmin ? "/api/manager/refresh" : "/api/user/refresh", {
      refreshToken,
    })
    .then((r) => {
      console.log("refresh token then", r);
      let result = r.data;
      console.log("result", result);
      localTokenStrategy.setToken(result.data.token);
      result.data.user.isChief = result.data.chief;
      result.data.user.isAdmin = isAdmin;
      if (!isAdmin) {
        result.data.user.organizationId = result.data.orgId;
      }
      localTokenStrategy.setUserInfo(result.data.user);
      return result.data.token.accessRefresh;
    })
    .catch((err) => {
      console.log("refresh token err", err);
      return "";
    })
    .finally(() => {
      isRefreshing = false;
    });
};

service.interceptors.request.use(
  async (config: any) => {
    let retry = new Promise((resolve, reject) => {
      subscribeTokenRefresh((token: string) => {
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        resolve(config);
      });
    });
    let access = localTokenStrategy.__getTokenObj();
    if (access && access.accessToken) {
      //有token
      let now = new Date();
      if (new Date(access.accessTokenExpiresAt) > now) {
        //token没过期
        onRefreshed(access.accessToken);
      } else if (new Date(access.accessRefreshExpiresAt) > now) {
        //token过期，但是没过刷新时间
        if (!isRefreshing) {
          //没有其他请求在刷新
          isRefreshing = true;
          onRefreshed(await refreshToken());
        }
      } else {
        //token彻底过期
        onRefreshed("");
      }
    } else {
      //没有token
      onRefreshed("");
    }
    return retry;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// request interceptor
// service.interceptors.request.use(
//   (config) => {
//     const headerBuilder = new HeaderBuilder(config.headers);
//     headerBuilder.add("Content-Type", "application/json");
//     if (localTokenStrategy.validToken(refreshToken)) {
//       headerBuilder.add(
//         "Authorization",
//         `Bearer ${localTokenStrategy.getToken()}`
//       );
//     }
//     config.headers = headerBuilder.build();
//     return config;
//   },
//   (error) => {
//     return Promise.reject(error);
//   }
// );

service.interceptors.response.use(
  (response) => {
    const res = response.data;
    res.isOk = res.code == 200;
    if (!res.isOk) {
      // Message({
      //   message: res.data,
      //   type: "error",
      //   duration: 5 * 1000,
      // });
      return Promise.reject(res);
    }
    return res as ResponseData;
  },
  (error) => {
    // Message({
    //   message: error?.response?.data?.data || "系统异常",
    //   type: "error",
    //   duration: 5 * 1000,
    // });
    if (error?.response?.status == 401) {
      if (
        error?.response?.data?.code == 40000 ||
        error?.response?.headers["content-type"]?.indexOf("text/html") > -1
      ) {
        //40000表示token有问题，必须重新登录
        //返回内容为HTML也必须重新登录
        localStorage.clear();
        window.location.reload();
        return;
      }
    }
    return Promise.reject(error?.response?.data);
  }
);

export default service;
